#include "Poller.h"
#include "Channel.h"
#include <sys/poll.h>

Poller::Poller(EventLoop *loop)
: _ownerLoop(loop) {}
Poller::~Poller() {}

Timestamp Poller::poll(int timeoutMs, ChannelList *activeChannels)
{
    int eventNum = ::poll(&*_pollfds.begin(), _pollfds.size(), timeoutMs);
    Timestamp now(Timestamp::now());
    if(eventNum > 0)
    {
        cout << eventNum << " events happened.\n";
        fillActiveChannels(eventNum, activeChannels);
    }
    else if(eventNum == 0)
    {
        cout << "nothing happened.\n";
    }
    else
    {
        perror("::poll");
        std::exit(1);
    }
    return now;
}

void Poller::fillActiveChannels(int eventNum, ChannelList *activeChannels) const 
{
    for (PollFdList::const_iterator pfd = _pollfds.begin();
         pfd != _pollfds.end(); ++pfd)
    {
        if(pfd->revents > 0)
        {
            --eventNum;
            ChannelMap::const_iterator ch = _channels.find(pfd->fd);
            assert(ch != _channels.end());
            Channel *pch = ch->second;
            assert(pch->fd() == pfd->fd);
            pch->set_revents(pfd->revents);
            activeChannels->push_back(pch);
        }
    }
}

void Poller::updateChannel(Channel *channel)
{
    assertInLoopThread();
    cout << "fd=" << channel->fd() << " events=" << channel->events() << "\n";
    if(channel->index() < 0)
    {
        //new 
        assert(_channels.find(channel->fd()) == _channels.end());
        struct pollfd pfd;
        pfd.fd = channel->fd();
        pfd.events = static_cast<short>(channel->events());
        pfd.revents = 0;
        _pollfds.push_back(pfd);
        int index = static_cast<int>(_pollfds.size()) - 1;
        channel->set_index(index);
        _channels[pfd.fd] = channel;
    }
    else
    {
        //update
        assert(_channels.find(channel->fd()) != _channels.end());
        assert(_channels[channel->fd()] == channel);
        int index = channel->index();
        assert(0 <= index && index < static_cast<int>(_pollfds.size()));
        struct pollfd &pfd = _pollfds[index];
        assert(pfd.fd == channel->fd() || pfd.fd == -1);
        pfd.events = static_cast<int>(channel->events());
        pfd.revents = 0;
        if(channel->isNoneEvent()) //无关注事件
        {//无视该pollfd 会丢失
            pfd.fd = -1;
            //优化:相反数-1 可恢复fd 减1原因：fd==1与原本-1冲突
        }
    }
}

void Poller::removeChannel(Channel *channel)
{
    assertInLoopThread();
    std::cerr << "Poller::removeChannel channel fd=" << channel->fd() << "\n";
    assert(_channels.find(channel->fd()) != _channels.end());
    assert(_channels[channel->fd()] == channel);
    assert(channel->isNoneEvent());
    int index = channel->index();
    assert(0 <= index && index < static_cast<int>(_pollfds.size()));
    const struct pollfd &pfd = _pollfds[index]; 
    assert(pfd.fd == channel->fd() && pfd.events == channel->events());
    size_t n = _channels.erase(channel->fd());
    assert(n == 1);
    if((size_t)index == _pollfds.size() - 1)
    {
        _pollfds.pop_back(); //删除最后一个
    }
    else
    {
        int lastIndex = static_cast<int>(_pollfds.size()) - 1;
        std::swap(_pollfds[index], _pollfds[lastIndex]); //交换最后一个
        Channel *lastChannel = _pollfds[lastIndex].fd < 0 ? NULL : _channels[_pollfds[lastIndex].fd];
        if(lastChannel)
        {
            lastChannel->set_index(index); //更新索引
        }
        _pollfds.pop_back();
    }
}